package com.weifly.weistock.web.controller.module;

import com.weifly.weistock.core.chart.ChartConverter;
import com.weifly.weistock.core.chart.bo.ChartConfigBO;
import com.weifly.weistock.core.chart.bo.ChartDataSetBO;
import com.weifly.weistock.core.common.Result;
import com.weifly.weistock.core.common.StockException;
import com.weifly.weistock.core.market.bo.StockDayBO;
import com.weifly.weistock.core.market.bo.StockKLineBO;
import com.weifly.weistock.core.monitor.bo.MonitorStatusBO;
import com.weifly.weistock.core.task.ThreadUpdateService;
import com.weifly.weistock.core.util.ConvertUtils;
import com.weifly.weistock.core.util.DateUtils;
import com.weifly.weistock.module.stockdata.StockDataConverter;
import com.weifly.weistock.module.stockdata.StockDataHoldService;
import com.weifly.weistock.module.stockdata.bo.GetDayListRequest;
import com.weifly.weistock.module.stockmonitor.StockMonitorConverter;
import com.weifly.weistock.module.stockmonitor.StockMonitorHoldService;
import com.weifly.weistock.module.stockmonitor.bo.StockMonitorDayBO;
import com.weifly.weistock.module.stockmonitor.bo.StockMonitorHoldBO;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

import javax.servlet.http.HttpServletRequest;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.List;
import java.util.Map;

import static com.weifly.weistock.core.constant.WeistockConstants.PAGE_LIMIT;

/**
 * 股票监控
 *
 * @author weifly
 * @since 2021/7/1
 */
@Controller
@RequestMapping(value = "/module/stockMonitor")
public class StockMonitorController {

    private Logger log = LoggerFactory.getLogger(StockMonitorController.class);

    @Autowired
    private StockDataHoldService stockDataHoldService;

    @Autowired
    private StockMonitorHoldService stockMonitorHoldService;

    @Autowired
    private ThreadUpdateService stockMonitorUpdateService;

    /**
     * 首页
     */
    @RequestMapping(value = "/index")
    public String index() {
        return "module/stockMonitor/index";
    }

    /**
     * 股票监控数据列表
     */
    @RequestMapping(value = "/stockList")
    public String stockList() {
        return "module/stockMonitor/stockList";
    }

    /**
     * 获取股票监控列表
     */
    @RequestMapping(value = "/getStockList")
    @ResponseBody
    public Result getStockList() {
        List<StockMonitorHoldBO> stockMonitorHoldList = this.stockMonitorHoldService.getStockList();
        List<Map<String, Object>> infoList = ConvertUtils.convert(stockMonitorHoldList, StockMonitorConverter::convertToStockMonitorDTO);
        return Result.createSuccessResult(infoList);
    }

    /**
     * 天数据列表
     */
    @RequestMapping(value = "/dayList")
    public String dayList(HttpServletRequest request) {
        String stockCode = request.getParameter("stockCode");
        if (StringUtils.isNotBlank(stockCode)) {
            StockMonitorHoldBO stockMonitorHoldBO = this.stockMonitorHoldService.getStock(stockCode);
            if (stockMonitorHoldBO != null) {
                request.setAttribute("stockMonitor", stockMonitorHoldBO.getStockMonitorConfig());
            }
        }
        return "module/stockMonitor/dayList";
    }

    /**
     * 加载天数据列表
     */
    @RequestMapping("/getDayList")
    @ResponseBody
    public Result getDayList(HttpServletRequest request) {
        GetDayListRequest getDayListRequest = StockDataConverter.convertToGetDayListRequest(request, PAGE_LIMIT);
        StockMonitorHoldBO stockMonitorHoldBO = this.stockMonitorHoldService.getStock(getDayListRequest.getStockCode());
        Map<String, Object> dataMap = StockMonitorConverter.getDayList(stockMonitorHoldBO, getDayListRequest);
        return Result.createSuccessResult(dataMap);
    }

    /**
     * 更新股票监控信息
     */
    @RequestMapping(value = "/updateStockMonitor")
    public String updateStockMonitor(HttpServletRequest request) {
        String stockCode = request.getParameter("stockCode");
        if (StringUtils.isNotBlank(stockCode)) {
            StockMonitorHoldBO stockMonitorHoldBO = this.stockMonitorHoldService.getStock(stockCode);
            if (stockMonitorHoldBO != null && stockMonitorHoldBO.getStockMonitorConfig() != null) {
                request.setAttribute("stockCode", stockMonitorHoldBO.getStockMonitorConfig().getStockCode());
                request.setAttribute("tradeStockCode", stockMonitorHoldBO.getStockMonitorConfig().getTradeStockCode());
            }
        }
        return "module/stockMonitor/updateStockMonitor";
    }

    /**
     * 根据股票K线数据，计算股票监控信息
     */
    @RequestMapping("/calcStockMonitor")
    @ResponseBody
    public Result calcStockMonitor(HttpServletRequest request) {
        String stockCode = request.getParameter("stockCode");
        if (StringUtils.isBlank(stockCode)) {
            return Result.createErrorResult("缺少参数：stockCode");
        }
        StockKLineBO stockKLine = this.stockDataHoldService.getStockData(stockCode);
        if (stockKLine == null) {
            return Result.createErrorResult("缺少KLine数据，stockCode=" + stockCode);
        }
        String tradeStockCode = request.getParameter("tradeStockCode");
        tradeStockCode = StringUtils.isBlank(tradeStockCode) ? null : tradeStockCode;
        this.stockMonitorHoldService.calcStockMonitor(stockKLine, tradeStockCode);
        // 重新计算每个股票status
        this.stockMonitorUpdateService.resetStatus();
        return Result.createSuccessResult(null);
    }

    /**
     * 更新所有股票监控信息
     */
    @RequestMapping("/doCalcAllStockMonitor")
    @ResponseBody
    public Result doCalcAllStockMonitor() {
        try {
            List<StockMonitorHoldBO> stockMonitorHoldList = this.stockMonitorHoldService.getStockList();
            for (StockMonitorHoldBO stockMonitorHoldBO : stockMonitorHoldList) {
                StockKLineBO stockKLineBO = this.stockDataHoldService.getStockData(stockMonitorHoldBO.getStockMonitorConfig().getStockCode());
                if (stockKLineBO == null || stockKLineBO.getDayList().isEmpty()) {
                    log.warn("无法加载KLine数据, stockCode={}, stockName={}", stockKLineBO.getStockCode(), stockKLineBO.getStockName());
                    continue;
                }
                this.stockMonitorHoldService.calcStockMonitor(stockKLineBO, stockMonitorHoldBO.getStockMonitorConfig().getTradeStockCode());
                log.info("更新股票监控数据，stockCode=" + stockKLineBO.getStockCode() + ", stockName=" + stockKLineBO.getStockName());
            }
            // 重新计算每个股票status
            this.stockMonitorUpdateService.resetStatus();
            return Result.createSuccessResult(null);
        } catch (StockException e) {
            return Result.createErrorResult(e);
        }
    }

    /**
     * 涨跌幅走势图
     */
    @RequestMapping(value = "/chart")
    public String chart(HttpServletRequest request) {
        Calendar lowDayCalc = Calendar.getInstance();
        lowDayCalc.add(Calendar.MONTH, -12);
        request.setAttribute("lowDay", new SimpleDateFormat(DateUtils.FORMATTER_DATE).format(lowDayCalc.getTime()));
        return "module/stockMonitor/chart";
    }

    /**
     * 加载涨跌幅 chart数据
     */
    @ResponseBody
    @RequestMapping("/loadChartData")
    public Result loadChartData(HttpServletRequest request) {
        ChartConfigBO chartConfig = ChartConverter.getChartConfig(request);
        ChartDataSetBO dataSet = new ChartDataSetBO();

        String stockCode = request.getParameter("stockCode");
        if (StringUtils.isBlank(stockCode)) {
            return Result.createErrorResult("缺少参数：stockCode");
        }
        StockKLineBO stockKLineBO = this.stockDataHoldService.getStockData(stockCode);
        if (stockKLineBO == null) {
            return Result.createErrorResult("无历史数据：" + stockCode);
        }

        // 加载股票天列表
        List<StockDayBO> stockDayList = StockDataConverter.loadStockDayList(stockKLineBO, chartConfig.getDay());
        StockMonitorConverter.fillDataSetByStockData(dataSet, stockDayList, stockKLineBO.getStockName());

        // 加载监控天列表
        StockMonitorHoldBO stockMonitorHoldBO = this.stockMonitorHoldService.getStock(stockCode);
        List<StockMonitorDayBO> stockMonitorDayList = StockMonitorConverter.loadStockMonitorDayList(stockMonitorHoldBO, chartConfig.getDay());
        StockMonitorConverter.fillDataSetByStockMonitorDayList(dataSet, stockMonitorDayList);

        return Result.createSuccessResult(dataSet);
    }

    /**
     * 股票监控页面
     */
    @RequestMapping(value = "/monitor")
    public String monitor() {
        return "module/stockMonitor/monitor";
    }

    /**
     * 加载监控状态
     */
    @ResponseBody
    @RequestMapping("/loadMonitorStatus")
    public Result loadMonitorStatus(HttpServletRequest request) {
        try {
            MonitorStatusBO statusBO = this.stockMonitorHoldService.getStatus();
            List<StockMonitorHoldBO> stockList = this.stockMonitorHoldService.getStockList();
            return Result.createSuccessResult(StockMonitorConverter.convertToMonitorStatus(statusBO, stockList));
        } catch (Exception e) {
            log.error("加载状态出错", e);
            return Result.createErrorResult("加载状态出错", null);
        }
    }
}
